#include "../include/Triangle.h"
#include <math.h>
#include <iostream>
#include "../include/HitPoint.h"


/**
* Procédure de calcul de l'intersection entre un rayon et un triangle
* @param orig point d'origine du rayon
* @param dir vecteur directeur du rayon
* @param vert0 1er point du triangle
* @param vert1 2eme point du triangle
* @param vert2 3eme point du triangle
* @return t distance entre l'origine et l'impact
* @return u coordonnées de textures
* @return v coordonnées de textures
* @return bool vrai si intersection, faux sinon
*/
bool intersectTriangle(pVect orig, pVect dir, pVect vert0, pVect vert1, pVect vert2, float &t, float &u, float &v)
{
  pVect edge1, edge2, tvec, pvec, qvec;
  float det,inv_det;
	bool it;

  edge1 = vert1 - vert0;
	edge2 = vert2 - vert0;
  pvec = dir ^ edge2;
  det = edge1 * pvec;
  if (det < 0.0) it=false;
  else {
    tvec = orig-vert0;
    u = tvec * pvec;
    if (u < 0.0 || u > det) it=false;
    else {
      qvec=tvec^edge1;
      v = dir*qvec;
      if (v < 0.0 || u + v > det) it=false;
      else {
        t = edge2*qvec;
        inv_det = 1.0 / det;
        t *= inv_det;
        u *= inv_det;
        v *= inv_det;
        it=true;
      }
    }
  }
  return it;
}


Triangle::Triangle()
{
}

/**
* Constructeur d'un triangle
* @param p1 1er point du triangle
* @param p2 2eme point du triangle
* @param p3 3eme point du triangle
* @return un triangle
*/
Triangle::Triangle(pVect p1, pVect p2, pVect p3){
    this->p1 = p1;
    this->p2 = p2;
    this->p3 = p3;
}


/**
* Constructeur d'un triangle
* @param p1 1er point du triangle
* @param p2 2eme point du triangle
* @param p3 3eme point du triangle
* @param materiaux le materiaux affecté au triangle
* @return un triangle
*/
Triangle::Triangle(pVect p1, pVect p2, pVect p3, Materiaux materiaux){
    this->p1 = p1;
    this->p2 = p2;
    this->p3 = p3;
    this->materiaux = materiaux;
}

Triangle::~Triangle()
{
    //dtor
}


/**
* Methode permettant de connaitre le point d'impact entre un rayon et un triangle
* @param origin origine du rayon
* @param rayon vecteur directeur du rayon lancé
* @return un point d'impact
*/
HitPoint* Triangle::intersect(pVect origin, pVect rayon){

    float t,u,v;
    if(intersectTriangle(origin,rayon,this->p1,this->p2,this->p3,t,u,v)){
        pVect pos = origin + rayon*t;
        pVect norm = (p2-p1)^(p3-p1);
        norm.normalize();
        if(t < 0) return 0;
        return new HitPoint(this, pos, norm, t, rayon,origin);
    }
    return 0;
}
